package server

import (
	"context"
	"fmt"
	mmd "github.com/go-kratos/kratos/v2/middleware/metadata"
	"github.com/go-kratos/kratos/v2/middleware/selector"
	"github.com/gorilla/handlers"
	v1 "kratos-realword/api/realworld/v1"
	"kratos-realword/internal/conf"
	"kratos-realword/internal/controller"
	"kratos-realword/internal/middleware/auth"
	netHttp "net/http"

	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/transport/http"
)

// NewWhiteListMatcher 白名单配置
func NewWhiteListMatcher() selector.MatchFunc {
	whiteList := make(map[string]struct{})
	whiteList["/realworld.v1.UserService/Login"] = struct{}{}
	whiteList["/realworld.v1.UserService/Register"] = struct{}{}
	return func(ctx context.Context, operation string) bool {
		if _, ok := whiteList[operation]; ok {
			return false
		}
		return true
	}
}

// NewHTTPServer new an HTTP server.
func NewHTTPServer(c *conf.Server,
	jwt *conf.JWT,
	articleService *controller.ArticleController,
	commentService *controller.CommentController,
	userService *controller.UserController,
	tagService *controller.TagController,
	profileService *controller.ProfileController,
	logger log.Logger) *http.Server {
	var opts = []http.ServerOption{
		//自定义错误返回
		http.ErrorEncoder(errorEncoder),
		http.Middleware(
			recovery.Recovery(),

			//设置 jwt 中间件
			selector.Server(auth.JwtAuth(jwt)).Match(NewWhiteListMatcher()).Build(),
			mmd.Server(),
		),

		http.Filter(
			//自定义Filter
			func(handler netHttp.Handler) netHttp.Handler {
				return netHttp.HandlerFunc(func(w netHttp.ResponseWriter, r *netHttp.Request) {
					fmt.Println("route filter in")
					handler.ServeHTTP(w, r)
					fmt.Println("route filter out")
				})
			},
			//设置跨域
			handlers.CORS(
				handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}),
				handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS", "DELETE"}),
				handlers.AllowedOrigins([]string{"*"}),
			)),
	}
	if c.Http.Network != "" {
		opts = append(opts, http.Network(c.Http.Network))
	}
	if c.Http.Addr != "" {
		opts = append(opts, http.Address(c.Http.Addr))
	}
	if c.Http.Timeout != nil {
		opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
	}
	srv := http.NewServer(opts...)
	v1.RegisterArticleServiceHTTPServer(srv, articleService)
	v1.RegisterCommentServiceHTTPServer(srv, commentService)
	v1.RegisterUserServiceHTTPServer(srv, userService)
	v1.RegisterTagServiceHTTPServer(srv, tagService)
	v1.RegisterProfileServiceHTTPServer(srv, profileService)

	return srv
}
